package serie08;

import java.util.Observable;

import serie08.DrinksMachineModel;
import serie06.util.CoinTypes;
import serie06.util.DrinkTypes;
import serie06.util.MoneyAmount;
import serie06.util.StdMoneyAmount;
import serie06.util.StdStock;
import serie06.util.Stock;

public class StdDrinksMachineModel extends Observable 
												implements DrinksMachineModel {

	// ATTRIBUTS
	
	private Stock<DrinkTypes> drinkStock;
	private MoneyAmount credit;
	private MoneyAmount cashbox;
	private MoneyAmount changebox;
	
	// CONSTRUCTEURS
	
	/**
	 * Modelise un distributeur.
	 * @post
	 *   drinkStock = new StdStock<DrinkTypes>(DrinkTypes.class)
	 *	 credit = new StdMoneyAmount()
	 * 	 cashbox = new StdMoneyAmount()
	 *	 changebox = new StdMoneyAmount()  
	 */
	public StdDrinksMachineModel() {
		drinkStock = new StdStock<DrinkTypes>(DrinkTypes.class);
		credit = new StdMoneyAmount();
		cashbox = new StdMoneyAmount();
		changebox = new StdMoneyAmount();
		setChanged();
	}
    // REQUETES
    
    public Stock<DrinkTypes> getDrinkStock() {
    	return drinkStock.clone();
    }
    
    public MoneyAmount getCredit() {
    	return credit.clone();
    }
    
    public MoneyAmount getCashbox() {
    	return cashbox.clone();
    }
    
    public MoneyAmount getChangebox() {
    	return changebox;
    }
    
    public boolean canGetChange() {
    	int lg = CoinTypes.values().length - 1;
    	int max = CoinTypes.values()[lg].getFaceValue();
    	for (int i = 1; i < max; i++) {
    		if (cashbox.computeChange(i) == null) {
    			return false;
    		}
    	}
    	return true;
    }
    
    // COMMANDES
    
    public void deliverDrink(DrinkTypes d) {
    	if (d == null) {
    		throw new IllegalArgumentException();
    	}
    	if (getDrinkStock().getNumber(d) < 1) {
    		throw new IllegalStateException();
    	}
    	if (getCredit().getAmount() < d.getPrice()) {
    		throw new IllegalStateException();
    	}
    	drinkStock.removeElement(d);
    	changebox.reset();
    	boolean b = canGetChange();
    	cashbox.addAmount(credit);
    	if (b) {
    		MoneyAmount monnaie = cashbox.computeChange(
    										credit.getAmount() - d.getPrice());
    		changebox.addAmount(monnaie);
    		cashbox.removeAmount(monnaie);
    	} 
    	credit.reset();
    	setChanged();
        notifyObservers(d);
    }
    
    public void fillStock() {
    	drinkStock.fill(MAX);
    	setChanged();
        notifyObservers();
    }
    
    public void fillCashbox() {
    	cashbox.fill(INIT);
    	setChanged();
        notifyObservers();
    }
    
    public void insertCoin(CoinTypes c) {
    	if (c == null) {
    		throw new IllegalArgumentException();
    	}
    	credit.addElement(c);
    	setChanged();
        notifyObservers();
    }
    
    public void resetCredit() {
    	changebox.reset();
    	changebox = getCredit();
    	credit.reset();
    	setChanged();
        notifyObservers();
    }
}
